/*
 *  texture.cpp
 *  BioBreak
 *
 *  Created by terry franguiadakis on 2/27/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#include "texture.h"
#include "render.h"

#include <OpenGLES/ES1/gl.h>
#include <OpenGLES/ES1/glext.h>

#include "importutils.h"

// -----------------------------------------------------------------------------


void CTexture::Apply() const
{
    glBindTexture(GL_TEXTURE_2D, m_texId);
}

void CTexture::Delete()
{
  //  SystemTextureDelete(m_texId);
}

// -----------------------------------------------------------------------------

void CTextureMgr::OnInit()
{
	m_missingTexture = CreateTexture("missing_texture.png");
    m_missingTextureAtlas = CreateTextureAtlas("missing_texture.png", 1, 1);
}

CTextureMgr::CTextureMgr() : super("texturemgr")
{

}

CTextureMgr::~CTextureMgr()
{
    for (int i = 0 ; i < m_textures.size(); i++)
    {
        delete m_textures[i]; // we should free it 
    }
}

const CTexture* CTextureMgr::GetLoadedTexture(const char* i_fileName)
{
	//search through and find the texture
	CTexture* foundTexture = NULL;
	for (int iTexture = 0; iTexture < m_textureFileNames.size(); ++iTexture)
	{
		if (m_textureFileNames[iTexture] == i_fileName)
		{
			foundTexture = m_textures[iTexture];
			break;
		}
	}

	return foundTexture;
}

const CTexture* CTextureMgr::CreateTexture(const char* i_filename)
{
	const CTexture* loadedTexture = GetLoadedTexture(i_filename);
	if (loadedTexture)
	{
		return loadedTexture;
	}
    
    CTexture texture;
    float maxS, maxT;
    
    if (SystemTextureLoad(i_filename, texture.m_texId, texture.m_width, texture.m_height, maxS, maxT))
    {
        m_textures.push_back(new CTexture(texture));
		m_textureFileNames.push_back(std::string(i_filename));
        return m_textures.back();
    }
    else
    {
       //report error
	   return m_missingTexture;
    }
}

const CTextureAtlas* CTextureMgr::CreateTextureAtlas(const char* i_filename, unsigned int i_xstep, unsigned int i_ystep)
{
    const CTexture* loadedTexture = GetLoadedTexture(i_filename);
    
    if (loadedTexture)
    {
        return static_cast<const CTextureAtlas*>(loadedTexture);
    }
    
    CTextureAtlas texture; 
    
    if (SystemTextureLoad(i_filename, texture.m_texId, texture.m_width, texture.m_height, texture.m_maxS, texture.m_maxT))
    {
        texture.m_xStep = i_xstep;
        texture.m_yStep = i_ystep;
        texture.setup();
        CTextureAtlas* textureAtlas = new CTextureAtlas(texture);
        m_textures.push_back(textureAtlas);
        m_textureFileNames.push_back(std::string(i_filename));
        return textureAtlas;
     }
    else {
        return m_missingTextureAtlas;
    }
}
                                            
CTextureCounter* CTextureMgr::CreateTextureCounter()
{
    if (m_textureCounter == NULL)
    {
        CTextureCounter texture; 
        
        if (SystemTextureLoad("numberAtlas.png", texture.m_texId, texture.m_width, texture.m_height, texture.m_maxS, texture.m_maxT))
        {
            texture.m_xStep = 17;
            texture.m_yStep = 1;
            texture.setup();
            m_textureCounter = new CTextureCounter(texture);
            m_textureCounter->SetString("0");
            m_textureCounter->SetInterval(10, 20);
        }
        else {
            return NULL; // signal error
        }        
    }
    
    return m_textureCounter;
}

void CTextureMgr::EnableTextures(bool i_enable)
{
    if (i_enable)
    {
        glEnable(GL_TEXTURE_2D);
    }
    else
    {
        glDisable(GL_TEXTURE_2D);
    }
}

// -----------------------------------------------------------------------------

void CTextureAtlas::Draw(const Vector2f& i_pos, const Vector2f& i_size, const Color4f& i_color, unsigned int i_frameNumber) const
{
    Apply();

    Vector2f incr(1, m_maxT/(m_yStep));
 
    if (i_frameNumber > m_quads.size())
    {
        return; // ERROR
    }
    
    Vector2f start = m_quads[i_frameNumber];
    Vector2f end   = m_quads[i_frameNumber+1];
    end.y = incr.y;
    BasicDrawObjects::DrawTexturedRect(i_pos, i_pos + i_size, i_color, start, end);
}

void CTextureAtlas::setup()
{
    int numSteps = (m_xStep * m_yStep) + 1;

    float maxS = m_maxS;  
    for (int i = 0 ; i < numSteps ; i++)
    {
        float x = (int(i % int(m_xStep-1))/(m_xStep-1)) * maxS;
        float y = (int(y / (m_xStep-1))/m_yStep) * m_maxT;
        
        m_quads.push_back(Vector2f(x,y));
    }
}

CTextureAtlas::~CTextureAtlas()
{
    m_quads.clear();
}

// -----------------------------------------------------------------------------

void CTextureCounter::Draw(const Vector2f& i_pos, const Color4f& i_color) const
{
    static const char* charSet = "./0123456789";
    static const size_t charSetLen = strlen(charSet);

    size_t len = m_stringdata.length();
    
    if (len == 0)
    {
        return ;
    }    
    
    const char* stringData = m_stringdata.c_str();

    for (int i = 0 ; i < len; i++)
    {
        char* pchar = (char*)memchr((void*)charSet, (int)stringData[i], charSetLen);
        if (pchar != NULL)
        {
            int location = pchar - charSet;
            float interval = i * m_xinterval;
            
            Vector2f a = i_pos + Vector2f(interval, 0.0);
            Vector2f b = Vector2f(m_xinterval, m_yinterval);
            CTextureAtlas::Draw(a,b, i_color, location);
        }
    }
}

// -----------------------------------------------------------------------------

void CLabel::Draw(const Vector2f& i_pos, const Color4f& i_color)
{
    Apply();

    float xs = m_width * m_maxS;
    float ys = m_height * m_maxT;
    float ratio = ys/xs;
    xs = 1.0f * (m_fontSize/2.0f) * m_height;
    ys = ratio * (m_fontSize/2.0f) * m_height;
    
    BasicDrawObjects::DrawTexturedRect(i_pos, i_pos + Vector2f(xs, ys), i_color, Vector2f(0.0, 0.0), Vector2f(m_maxS, m_maxT));

}

// -----------------------------------------------------------------------------


